import type { SetupContext, VNode } from 'vue'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import { h, reactive, ref, watch, markRaw, defineComponent, KeepAlive, toRaw } from 'vue'
import BUS_EVENT_KEYS from '@jsjn/micro-core-micro-main/wujie/constants/BUS_EVENT_KEYS'
import _ from 'lodash'
import { global } from '@jsjn/utils'

const workflowCacheSuffix = '_workflow_cace'

interface Params {
    Component: VNode
    route: RouteLocationNormalizedLoaded
    key: string
}

// 模块应用缓存列表
const cached = reactive<{ [k: string]: { pageId: string; component: VNode } }>({})
export const includes = ref([])
watch(
    () => cached,
    () => {
        includes.value = Object.keys(cached)
    },
    { deep: true }
)

// 系统关闭标签页时，微应用 移除不存在于标签栏的缓存页
window.$wujie?.bus.$on(BUS_EVENT_KEYS['BASIC_TAGS_CLOSED'], function (viableTags: string[]) {
    Object.keys(cached).forEach((cacheKey) => {
        // 工作流存活，不处理其缓存页面
        if (viableTags.includes('workflow-root') && cacheKey.includes(workflowCacheSuffix)) {
            return
        }

        if (!viableTags.map((tag) => tag?.replaceAll('/', '_')).includes(cacheKey)) {
            removeComponentCache(cacheKey)
        }
    })
})

/**
 * 包装器 核心思想：动态追加、控制需要缓存的页面
 * @param param0
 * @returns
 */
export function reDefineComponent({ Component, route, key }: Params) {
    /**
     * 这里为了防止应用缓存时，基座触发 “关闭通信（应用未显示时，接收了路由通信）”，导致缓存的页面二次执行生命周期
     * 如果在离开微应用时，满足如下条件
     *  1. 微应用缓存
     *  2. 离开的页面缓存
     * 在双重缓存下，基子通信时，缓存的页面 “缓存组件” 依然会响应变化
     * 导致 “页面组件” 二次初始化执行
     * 在保证只有在当前组件路由和基座 url 一致的情况下，才继续渲染
     * 否则，阻止渲染
     * 
     * ------- 
     * 2024/12/11 fix: 这里的判定基座路径必须包含当前微应用页面路由才渲染的情况，不适用于 ‘selectMenu’ 内部显示的页面，配置 mode=center 的页面
     */
    if (
        !Component ||
        (!global.location.href.includes(route.path) && !global.location.href.includes('selectMenu'))
    ) {
        return null
    }

    const {
        name,
        meta: { isCache: configIsCache },
        query: { isCache: routeQueryIsCache }
    } = route

    const isCache = configIsCache === true || routeQueryIsCache === 'true'
    /**
     * 包含工作流，在工作流中，建立和非工作流中的特殊缓存
     * 工作流一旦关闭后，就默认清理掉其缓存
     */
    let pageId = (name as string)?.replaceAll('/', '_')
    if (pageId && global['__IS_WORKFLOW__']) {
        pageId += `${workflowCacheSuffix}_${
            route.query.workItemId || route.query.processInstId || ''
        }`
    }

    // 非缓存
    if (!isCache || !pageId) return h(Component, { key })

    // 已缓存
    const componentCache = cached[pageId]
    if (componentCache?.component) return h(componentCache.component, { key })

    // 新的
    const newComponent = markRaw(
        defineComponent({
            name: pageId,
            render: () => Component
        })
    )

    // 保留自定义缓存的组件
    cached[pageId] = {
        pageId,
        component: newComponent as any
    }

    return h(newComponent, { key })
}

export function removeComponentCache(pageId) {
    if (cached[pageId]) {
        delete cached[pageId]
    }
}
